package com.gosophia.dataDictionary.test.integration;

import java.util.ArrayList;
import java.util.List;

import junit.framework.Assert;

import org.hibernate.JDBCException;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.transaction.annotation.Transactional;

import com.gosophia.commons.OrderCondition;
import com.gosophia.commons.Page;
import com.gosophia.commons.exception.BusinessException;
import com.gosophia.commons.exception.ConcurrencyException;
import com.gosophia.dataDictionary.dao.DataEntryDAO;
import com.gosophia.dataDictionary.dao.DataValueDAO;
import com.gosophia.dataDictionary.entity.DataEntry;
import com.gosophia.dataDictionary.entity.DataValue;
import com.gosophia.dataDictionary.service.DataDictionaryService;

/**
 * DataDictionaryServiceImpl类的集成测试类
 * 
 * @author tianchunyu
 * @date 2010-8-9
 */
@ContextConfiguration(locations = { "classpath*:moduleContext.xml",
        "classpath:applicationContext-it.xml" })
@Transactional(rollbackFor = { BusinessException.class })
@TransactionConfiguration(defaultRollback = true)
public class ITDataDictionaryServiceImpl extends
        AbstractTransactionalJUnit4SpringContextTests {

    @Autowired
    private DataDictionaryService dataDictionaryService;

    @Autowired
    private SessionFactory sf;

    @Autowired
    private DataEntryDAO dataEntryDAO;

    @Autowired
    private DataValueDAO dataValueDAO;

    /**
     * 测试findEntriesByPage方法，当pageNo不大于0时
     */
    @Test(expected = IllegalArgumentException.class)
    public void testFindDataEntriesByPageWithPageNoIs0() {
        dataDictionaryService.findDataEntriesByPage(0, 10, "",
                new ArrayList<OrderCondition>());
    }

    @Test(expected = IllegalArgumentException.class)
    public void testFindEntriesByPageWithPageNoLessThen0() {
        dataDictionaryService.findDataEntriesByPage(-1, 10, "",
                new ArrayList<OrderCondition>());
    }

    /**
     * 测试findEntriesByPage方法，当查询条件为null
     */
    @Test()
    public void testFindEntriesByPageWithConditionNull() {
        dataDictionaryService.findDataEntriesByPage(1, 10, null,
                new ArrayList<OrderCondition>());
    }

    /**
     * 测试findEntriesByPage方法，当pageSize不大于0时
     */
    @Test(expected = IllegalArgumentException.class)
    public void testFindEntriesByPageWithPageSizeIs0() {
        dataDictionaryService.findDataEntriesByPage(1, 0, "",
                new ArrayList<OrderCondition>());
    }

    @Test(expected = IllegalArgumentException.class)
    public void testFindEntriesByPageWithPageSizeLessThen0() {
        dataDictionaryService.findDataEntriesByPage(1, -1, "",
                new ArrayList<OrderCondition>());
    }

    /**
     * 测试findEntriesByPage方法，当正常返回时
     */
    @Test()
    public void testFindEntriesByPage() {
        Page<DataEntry> page1 = dataDictionaryService.findDataEntriesByPage(1,
                10, "", null);
        System.out.println("-------------------------------");
         Assert.assertEquals(10, page1.getResult().size());
        // Assert.assertEquals(20, page.getTotalCount());
        Page<DataEntry> page2 = dataDictionaryService.findDataEntriesByPage(2,
                10, "", null);
        System.out.println("-------------------------------");
        Page<DataEntry> page3 = dataDictionaryService.findDataEntriesByPage(3,
                10, "", null);
        System.out.println("-------------------------------");
        Page<DataEntry> page4 = dataDictionaryService.findDataEntriesByPage(1,
                30, "", null);

        System.out.println("-------------------------------");

        for (DataEntry de : page1.getResult()) {
            System.out.println(de.getEntryNameCN());
        }
        System.out.println("-------------------------------");
        for (DataEntry de : page2.getResult()) {
            System.out.println(de.getEntryNameCN());
        }
        System.out.println("-------------------------------");
        for (DataEntry de : page3.getResult()) {
            System.out.println(de.getEntryNameCN());
        }
        System.out.println("-------------------------------");
        for (DataEntry de : page4.getResult()) {
            System.out.println(de.getEntryNameCN());
        }
    }

    /**
     * 测试findEntryById方法，当id为null时
     */
    @Test(expected = IllegalArgumentException.class)
    public void testFindEntryByIdWithNull() {
        dataDictionaryService.findDataEntryById(null);
    }

    /**
     * 测试findEntryById方法，当id不存在时
     */
    @Test(expected = ConcurrencyException.class)
    public void testFindEntryByIdWithNoId() {
        dataDictionaryService.findDataEntryById(999L);
    }

    /**
     * 测试findEntryById方法，正常时
     */
    @Test
    public void testFindEntryById() {
        DataEntry entry = dataDictionaryService.findDataEntryById(1016L);
        Assert.assertEquals("性别", entry.getEntryNameCN());
    }

    /**
     * 测试findEnabledDAtaValueByEntryId方法，当entryId为null时
     */
    @Test(expected = IllegalArgumentException.class)
    public void testFindEnabledDataValueByEntryIdWithNull() {
        dataDictionaryService.findEnabledDataValueByEntryId(null);
    }

    /**
     * 测试findEnabledDAtaValueByEntryId方法，当entryId不存在时
     */
    @Test
    public void testFindEnabledDataValueByEntryIdWithNoEntryId() {
        Assert.assertEquals(0, dataDictionaryService
                .findEnabledDataValueByEntryId(111L).size());
    }

    /**
     * 测试findEnabledDAtaValueByEntryId方法，一般情况下
     */
    @Test
    public void testFindEnabledDataValueByEntryId() {
        List<DataValue> result = dataDictionaryService
                .findEnabledDataValueByEntryId(1016L);
        int count = result.size();
        String kk = result.get(0).getKey();
        String vv = result.get(0).getValue();
        Assert.assertEquals(1, count);
        Assert.assertEquals("002", kk);
        Assert.assertEquals("女", vv);
    }

    /**
     * 测试findDataValueByEntryIdAndKey方法，当entryId为null时
     */
    @Test(expected = IllegalArgumentException.class)
    public void testFindDataValueByEntryIdAndKeyWithEntryIdNull() {
        dataDictionaryService.findDataValueByEntryIdAndKey(null, "qq");
    }

    /**
     * 测试findDataValueByEntryIdAndKey方法，当key为null时
     */
    @Test(expected = IllegalArgumentException.class)
    public void testFindDataValueByEntryIdAndKeyWithKeyNull() {
        dataDictionaryService.findDataValueByEntryIdAndKey(11L, null);
    }

    /**
     * 测试findDataValueByEntryIdAndKey方法，一般情况下
     */
    @Test
    public void testFindDataValueByEntryIdAndKey() {
        DataValue result = dataDictionaryService.findDataValueByEntryIdAndKey(
                1016L, "001");
        Assert.assertEquals("001", result.getKey());
        Assert.assertEquals("男", result.getValue());
    }

    /**
     * 测试addDataValue方法，当dataValue为null时
     */
    @Test(expected = IllegalArgumentException.class)
    public void testAddDataValueWithNull() throws BusinessException {
        dataDictionaryService.addDataValue(null, null);
    }

    /**
     * 测试addDataValue方法，当dataValueId不为null时
     */
    @Test(expected = IllegalArgumentException.class)
    public void testAddDataValueWithNotNullId() throws BusinessException {
        DataValue dataValue = new DataValue();
        ReflectionTestUtils.setField(dataValue, "dataValueId", 110L);
        dataDictionaryService.addDataValue(dataValue, null);
    }

    /**
     * 测试addDataValue方法，当出现相同的key时
     */
    @Test(expected = BusinessException.class)
    public void testAddDataValueWithSameValue() throws BusinessException {
        DataValue dataValue = new DataValue();
        dataValue.setDataEntry(dataEntryDAO.get(1016L));
        dataValue.setKey("001");
        dataDictionaryService.addDataValue(dataValue, null);
    }

    /**
     * 测试addDataValue方法，当出现相同的值时
     */
    @Test(expected = BusinessException.class)
    public void testAddDataValueWithSameKey() throws BusinessException {
        DataValue dataValue = new DataValue();
        dataValue.setDataEntry(dataEntryDAO.get(1016L));
        dataValue.setValue("男");
        dataDictionaryService.addDataValue(dataValue, null);
    }

    /**
     * 测试addDataValue方法,添加到最顶端
     */
    @Test
    public void testAddDataValueNomal1() throws BusinessException,
            ConcurrencyException {
        DataValue dataValue = new DataValue();
        dataValue.setDataEntry(dataEntryDAO.get(1016L));
        dataValue.setIsEnabled(true);
        dataValue.setKey("010");
        dataValue.setValue("中性");
        dataDictionaryService.addDataValue(dataValue, null);
        dataEntryDAO.flush();
        dataValueDAO.clearEntityOnSession(dataValue);
        List<DataValue> dvs = dataValueDAO.getByProperty("dataEntry.entryId",
                1016L);
        Assert.assertEquals(3, dvs.size());
    }

    /**
     * 测试addDataValue方法,添加到中间
     */
    @Test
    public void testAddDataValueNomal2() throws BusinessException,
            ConcurrencyException {
        DataValue dataValue = new DataValue();
        dataValue.setDataEntry(dataEntryDAO.get(1016L));
        dataValue.setIsEnabled(true);
        dataValue.setKey("010");
        dataValue.setOrderIndex(4);
        dataValue.setValue("中性");
        dataDictionaryService.addDataValue(dataValue, 1032L);
        dataEntryDAO.flush();
        dataValueDAO.clearEntityOnSession(dataValue);
        List<DataValue> dvs = dataValueDAO.getByProperty("dataEntry.entryId",
                1016L);
        Assert.assertEquals(3, dvs.size());
    }

    /**
     * 测试updateDataValue方法，当dataValue为null时
     */
    @Test(expected = IllegalArgumentException.class)
    public void testUpdateDataValueWithNull() throws BusinessException,
            ConcurrencyException {
        dataDictionaryService.updateDataValue(null);
    }

    /**
     * 测试updateDataValue方法，当dataValueId为null时
     */
    @Test(expected = IllegalArgumentException.class)
    public void testUpdateDataValueWithNullId() throws BusinessException,
            ConcurrencyException {
        DataValue dataValue = new DataValue();
        ReflectionTestUtils.setField(dataValue, "dataValueId", null);
        dataDictionaryService.updateDataValue(dataValue);

    }

    /**
     * 测试updateDataValue方法，当出现相同的key时
     */
    @Test(expected = BusinessException.class)
    public void testUpdateDataValueWithSameKey() throws BusinessException,
            ConcurrencyException {
        DataValue dv = new DataValue();
        ReflectionTestUtils.setField(dv, "dataValueId", 1031L);
        dv.setDataEntry(dataEntryDAO.get(1016L));
        dv.setKey("002");
        dv.setIsEnabled(true);
        dv.setOrderIndex(10);
        dv.setValue("中性");
        dataDictionaryService.updateDataValue(dv);
    }

    /**
     * 测试updateDataValue方法，当出现相同的值时
     */
    @Test(expected = BusinessException.class)
    public void testUpdateDataValueWithSameValue() throws BusinessException,
            ConcurrencyException {
        DataValue dv = new DataValue();
        ReflectionTestUtils.setField(dv, "dataValueId", 1031L);
        dv.setDataEntry(dataEntryDAO.get(1016L));
        dv.setKey("010");
        dv.setIsEnabled(true);
        dv.setOrderIndex(10);
        dv.setValue("女");
        dataDictionaryService.updateDataValue(dv);
    }

    /**
     * 测试updateDataValue方法，一般情况下
     */
    @Test
    public void testUpdateDataValue() throws BusinessException,
            ConcurrencyException {
        DataValue dv = dataValueDAO.get(1031L);
        dv.setValue("不详");
        dataDictionaryService.updateDataValue(dv);
    }

    /**
     * 测试removeDataValue方法，当dataValueId为null时
     */
    @Test(expected = IllegalArgumentException.class)
    public void testRemoveDataValueWithNullId() throws BusinessException,
            ConcurrencyException {
        dataDictionaryService.removeDataValue(null, 1L);
    }

    /**
     * 测试removeDataValue方法，当version为null时
     */
    @Test(expected = IllegalArgumentException.class)
    public void testRemoveDataValueWithNullVersion() throws BusinessException,
            ConcurrencyException {
        dataDictionaryService.removeDataValue(110L, null);
    }

    /**
     * 测试removeDataValue方法，当值被引用时
     * 
     */
    @Test(expected = ConcurrencyException.class)
    public void testRemoveDataValueUsed() throws BusinessException,
            ConcurrencyException {
        dataDictionaryService.removeDataValue(1L, 0L);
    }

    /**
     * 测试removeDataValue方法，当值已被其他用户更改时(version不同时)
     */
    @Test(expected = ConcurrencyException.class)
    public void testRemoveDataValueWithNoSameVersion()
            throws BusinessException, ConcurrencyException {
        dataDictionaryService.removeDataValue(1031L, 2L);
    }

    /**
     * 测试removeDataValue方法，当值没有被引用时（正常删除情况）
     */
    @Test
    public void testRemoveDataValueUnused() throws BusinessException,
            ConcurrencyException {
        dataDictionaryService.removeDataValue(1035L, 0L);
        Assert.assertEquals(7, dataValueDAO.get(1040L).getOrderIndex());
    }

    /**
     * 测试findDataValueByDataValueId方法,当id为null时
     */
    @Test(expected = IllegalArgumentException.class)
    public void testFindDataValueByDataValueIdWithIdNull() {
        dataDictionaryService.findDataValueByDataValueId(null);
    }

    /**
     * 测试findDataValueByDataValueId方法,当id不存在时
     */
    @Test(expected = ConcurrencyException.class)
    public void testFindDataValueByDataValueIdWithNotExitId() {
        dataDictionaryService.findDataValueByDataValueId(1L);
    }

    /**
     * 测试findDataValueByDataValueId方法
     */
    @Test
    public void testFindDataValueByDataValueIdNormal() {
        DataValue dataValue = dataDictionaryService
                .findDataValueByDataValueId(1001L);
        Assert.assertEquals("日常业务", dataValue.getValue());
    }

    @Test(expected = IllegalArgumentException.class)
    public void testFindDataValueByEntryNameAndKeyWithEntryNameNull() {
        dataDictionaryService.findDataValueByEntryNameAndKey(null, "");
    }

    @Test(expected = IllegalArgumentException.class)
    public void testFindDataValueByEntryNameAndKeyWithKeyNull() {
        dataDictionaryService.findDataValueByEntryNameAndKey("", null);
    }

    @Test
    public void testFindDataValueByEntryNameAndKey() {
        DataValue dataValue = dataDictionaryService
                .findDataValueByEntryNameAndKey("性别", "001");
    }

    @Test(expected = IllegalArgumentException.class)
    public void testFindEnabledDataValueByEntryNameWithEntryNameNull() {
        dataDictionaryService.findEnabledDataValueByEntryName(null);
    }

    @Test
    public void testFindEnabledDataValueByEntryName() {
        List<DataValue> dataValues = dataDictionaryService
                .findEnabledDataValueByEntryName("sex");
        Assert.assertEquals(1, dataValues.size());
    }

    @Test(expected = IllegalArgumentException.class)
    public void testRemoveDataValueWithNull() throws BusinessException {
        dataDictionaryService.removeDataValue(null);
    }

    @Test(expected = JDBCException.class)
    public void testRemoveDataValueWithUnNormal() throws BusinessException {
        DataValue dataValue = dataValueDAO.get(1031L);
        dataDictionaryService.removeDataValue(dataValue);
    }

    @Test
    public void testRemoveDataValue() throws BusinessException {
        DataValue dataValue = dataValueDAO.get(1008L);
        dataDictionaryService.removeDataValue(dataValue);
        DataValue dataValue1 = dataValueDAO.get(1008L);
        Assert.assertNull(dataValue1);
    }

    /**
     * 测试向上移动
     */
    @Test
    public void testMoveDataValueUp() {
        dataDictionaryService.moveDataValue(1033L, 1038L, 1025L);
        Query q = sf
                .getCurrentSession()
                .createQuery(
                        "from DataValue d where d.dataEntry.entryId = ? order by d.orderIndex desc");
        q.setLong(0, 1025L);
        List<DataValue> list = q.list();

        Assert.assertEquals(12, list.size());
        Assert.assertEquals("回族", list.get(11).getValue());
        Assert.assertEquals(1, list.get(11).getOrderIndex());
        Assert.assertEquals("汉族", list.get(7).getValue());
        Assert.assertEquals(5, list.get(7).getOrderIndex());

    }

    /**
     * 测试向下移动
     */
    @Test
    public void testMoveDataValueDown() {
        dataDictionaryService.moveDataValue(1038L, 1035L, 1025L);
        Query q = sf
                .getCurrentSession()
                .createQuery(
                        "from DataValue d where d.dataEntry.entryId = ? order by d.orderIndex desc");
        q.setLong(0, 1025L);
        List<DataValue> list = q.list();

        Assert.assertEquals(12, list.size());
        Assert.assertEquals("壮族", list.get(8).getValue());
        Assert.assertEquals(4, list.get(8).getOrderIndex());
        Assert.assertEquals("彝族", list.get(9).getValue());
        Assert.assertEquals(3, list.get(9).getOrderIndex());
    }

    /**
     * 测试移动到最上面
     */
    @Test
    public void testMoveDataValueFirst() {
        dataDictionaryService.moveDataValue(1042L, null, 1025L);
        Query q = sf
                .getCurrentSession()
                .createQuery(
                        "from DataValue d where d.dataEntry.entryId = ? order by d.orderIndex desc");
        q.setLong(0, 1025L);
        List<DataValue> list = q.list();

        Assert.assertEquals(12, list.size());
        Assert.assertEquals("朝鲜族", list.get(0).getValue());
        Assert.assertEquals(12, list.get(0).getOrderIndex());
        Assert.assertEquals("瑶族", list.get(1).getValue());
        Assert.assertEquals(11, list.get(1).getOrderIndex());
    }
}

// /:~
